﻿#include "monitorutil.h"
#include <QCoreApplication>
#include <QSysInfo>
#include "utils/sysinfo.hpp"

MonitorUtil::MonitorUtil()
{
    JQCPUMonitor::initialize();
}

MonitorUtil* MonitorUtil::instance(){
    return mnrInstance();  // 返回线程安全的静态对象
}

//获取静态数据
void MonitorUtil::init()
{
    data.system.qtVersion = QT_VERSION_STR;
    data.system.startTime = QDateTime::currentDateTime();
    data.system.exeDir = QCoreApplication::applicationDirPath();
    data.system.machineName = QSysInfo::machineHostName();
    data.system.osVersion = QSysInfo::productType();
    data.system.kernelType = QSysInfo::kernelType();
    data.system.kernelVersion = QSysInfo::kernelVersion();
    data.cpu.architecture = QSysInfo::currentCpuArchitecture();

    QList<QMap<QString, QString>> cpuInfo = SysInfo::getCpuAndGpuInfo();
    for (auto map: cpuInfo)
    {
        if(map.contains("CPU"))
            data.cpu.cpuName = map["CPU"];
        if(map.contains("CPU Number"))
            data.cpu.cpuNumber = map["CPU Number"].toInt();
        if(map.contains("CPU Logical"))
            data.cpu.cpuLogical = map["CPU Logical"].toInt();
        if(map.contains("GPU"))
            data.machine.gpuName = map["GPU"];
    }

    QList<QMap<QString, QString>> biosInfo = SysInfo::getBiosInfo();
    for (auto map: biosInfo)
    {
        if(map.contains("BaseBoard Manufacturer"))
            data.machine.baseBoardManufacturer = map["BaseBoard Manufacturer"];
        if(map.contains("BaseBoard Product"))
            data.machine.baseBoardProduct = map["BaseBoard Product"];
        if(map.contains("BIOS Vendor"))
            data.machine.biosVendor = map["BIOS Vendor"];
        if(map.contains("BIOS Release Date"))
            data.machine.biosReleaseDate = map["BIOS Release Date"];
        if(map.contains("System Manufacturer"))
            data.machine.systemManufacturer = map["System Manufacturer"];
        if(map.contains("Product Name"))
            data.machine.productName = map["Product Name"];
    }

    QList<QMap<QString, QString>> diskInfo = SysInfo::getDiskInformation();
    for (auto map: diskInfo)
    {
        MonitorDisk disk;
        if(map.contains("Root"))
            disk.diskName = map["Root"];
        if(map.contains("File system"))
            disk.type = map["File system"];
        if(map.contains("Space available"))
            disk.free = map["Space available"];
        if(map.contains("Total space"))
            disk.total = map["Total space"];
        if(map.contains("Used space"))
            disk.used = map["Used space"];
        if(map.contains("Usage"))
            disk.usage = map["Usage"].toFloat();

        data.disks.append(disk);
    }
}

void MonitorUtil::getMonitorData()
{
    qint64 seconds =
            (QDateTime::currentMSecsSinceEpoch() - data.system.startTime.toMSecsSinceEpoch()) / 1000;

    data.system.runSeconds = getTimeStrFromSec(seconds);

    getMemory();
    getUsedMemory(GetCurrentProcessId());

    data.cpu.usage = JQCPUMonitor::cpuUsagePercentage() * 100;
    data.cpu.usage5s = JQCPUMonitor::cpuUsagePercentageIn5Second() * 100;
    data.cpu.usage30s = JQCPUMonitor::cpuUsagePercentageIn30Second() *100;
    data.cpu.usage300s = JQCPUMonitor::cpuUsagePercentageIn5Minute() * 100;
}

/**
  * @author yuliuchuan
  * @date 2015-04-10
  * 查询程序占用内存。
  * 思路：通过调用外部命令'tasklist /FI "PID EQ pid"'。
  * 将返回的字符串首先替换掉','，
  * 然后用正则表达式匹配已KB为单位表示内存的字符串，
  * 最后换算为MB为单位返回。
  */
void MonitorUtil::getUsedMemory(DWORD pid)
{
    char pidChar[25];
    //将DWORD类型转换为10进制的char*类型
    _ultoa(pid,pidChar,10);

    //调用外部命令
    QProcess p;
    p.start("tasklist /FI \"PID EQ " + QString(pidChar) + " \"");
    p.waitForFinished();
    //得到返回结果
    QString result = QString::fromLocal8Bit(p.readAllStandardOutput());
    //关闭外部命令
    p.close();

    //替换掉","
    result = result.replace(",","");
    //匹配 '数字+空格+K'部分。
    QRegExp rx("(\\d+)(\\s)(K)");
    //初始化结果
    QString usedMem("");
    if(rx.indexIn(result) != -1){
        //匹配成功
        usedMem = rx.cap(0);
    }
    //截取K前面的字符串，转换为数字，供换算单位使用。
    usedMem = usedMem.left(usedMem.length() - 1);

    //换算为MB的单位
    QString mb = QString::number(usedMem.toDouble() / 1024) + " MB";

    data.memory.current = usedMem.toDouble() / 1024;
}

#define GB (1024*1024*1024)
void MonitorUtil::getMemory()
{
    MEMORYSTATUSEX statex;
    statex.dwLength = sizeof(statex);
    GlobalMemoryStatusEx(&statex);
    double m_totalMem = statex.ullTotalPhys * 1.0/ GB;
    double m_freeMem = statex.ullAvailPhys * 1.0 / GB;

    data.memory.total = m_totalMem;
    data.memory.free = m_freeMem;
    data.memory.used = m_totalMem - m_freeMem;
    data.memory.usage = data.memory.used *100 / m_totalMem;

    QString m_memDescribe = QStringLiteral("可用%1 GB/共共%2 GB")
            .arg(QString::asprintf("%.2f", m_freeMem))
            .arg(QString::asprintf("%.2f", m_totalMem));

}
//将秒数转化为时分秒格式
QString MonitorUtil::getTimeStrFromSec(qint64 seconds)
{
    int H = seconds / (60*60);
    int M = (seconds- (H * 60 * 60)) / 60;
    int S = (seconds - (H * 60 * 60)) - M * 60;
    QString hour = QString::number(H);
    if (hour.length() == 1)
        hour = "0" + hour;
    QString min = QString::number(M);
    if (min.length() == 1)
        min = "0" + min;
    QString sec = QString::number(S);
    if (sec.length() == 1) sec = "0" + sec;
    QString qTime = hour + ":" + min + ":" + sec;
    return qTime;
}
